package com.foreverwin.jzymes.common.service.impl;

import com.foreverwin.jzymes.common.constant.Constants;
import com.foreverwin.jzymes.common.mapper.ResourceAdviceMapper;
import com.foreverwin.jzymes.common.service.*;
import com.foreverwin.jzymes.common.util.BOHandleUtil;
import com.foreverwin.jzymes.eap.domain.ResourceTimeLog;
import com.foreverwin.jzymes.eap.mapper.ResourceTimeLogAdviceMapper;
import com.foreverwin.jzymes.eap.service.IResourceTimeLogService;
import com.foreverwin.jzymes.framework.exception.BusinessException;
import com.foreverwin.jzymes.framework.util.I18nUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.*;

@Service
public class ResourceAdviceServiceImpl implements IResourceAdviceService {

    @Autowired
    ISiteAdviceService siteAdviceService;
    @Autowired
    ICustomFieldsAdviceService customFieldsAdviceService;
    @Autowired
    IResourceTimeLogService resourceTimeLogService;
    @Autowired
    ISystemRuleAdviceService systemRuleAdviceService;
    @Autowired
    IResourceTypeAdviceService resourceTypeAdviceService;
    @Autowired
    ResourceTimeLogAdviceMapper resourceTimeLogAdviceMapper;
    @Autowired
    ResourceAdviceMapper resourceAdviceMapper;

    private static Map<String,List<String>> resourceStatusMap = new HashMap<>();

    /**
     * 检查设备
     *
     * @param site
     * @param resource
     * @return
     */
    public Map<String,Object> existResource( String site, String resource ){

        Map<String,Object> resourceMap = findResource( site, resource );
        /**检查设备是否存在*/
        Assert.notNull( resourceMap, I18nUtil.getI18nText( "common.resourceNotExist", new String[]{ resource } ) );

        return resourceMap;
    }

    /**
     * 查询设备
     *
     * @param site
     * @param resource
     * @return
     */
    public Map<String,Object> findResource( String site, String resource ){
        /**检查站点*/
        siteAdviceService.existSite( site );
        /**检查设备编号*/
        Assert.hasText( resource, I18nUtil.getI18nText("common.resourceNotBlank") );

        Map<String,Object> resourceMap = resourceAdviceMapper.selectResourceMap( site, resource );

        return resourceMap;
    }

    /**
     * 通过设备编号获取工序
     *
     * @param site
     * @param resource
     * @return
     */
    public String findOperationByResource(String site, String resource ){
        String operationBo = findOperationBoByResource( site, resource );
        String[] parts = BOHandleUtil.splitOperationHandle( operationBo );
        Assert.isTrue( parts.length > 0, I18nUtil.getI18nText( "common.operationOnResourceNotExist", new String[]{ resource } ) );
        return parts[1];
    }

    /**
     * 通过设备编号获取工序
     *
     * @param site
     * @param resource
     * @return
     */
    public String findOperationBoByResource( String site, String resource ){
        Map<String,Object> resourceMap = existResource( site,resource );
        String operationBo = (String) resourceMap.get( "OPERATION_BO" );
        Assert.hasText( operationBo, I18nUtil.getI18nText( "common.operationOnResourceNotExist", new String[]{ resource } ) );
        return operationBo;
    }

    /**
     * 通过设备编号获取工序
     *
     * @param resourceMap
     * @return
     */
    public String findOperationByResource(Map<String,Object> resourceMap ){
        /**检查设备是否存在*/
        Assert.notNull( resourceMap, I18nUtil.getI18nText( "common.resourceNotExist", new String[]{ } ) );
        String operationBo = (String) resourceMap.get( "OPERATION_BO" );
        String[] parts = BOHandleUtil.splitOperationHandle( operationBo );
        Assert.isTrue( parts.length > 0, I18nUtil.getI18nText( "common.operationOnResourceNotExist", new String[]{(String) resourceMap.get( "RESRCE" )} ) );
        return parts[1];
    }

    /**
     * 查询资源夹位
     *
     * @param site
     * @param resource
     * @return
     */
    public String findCncType( String site, String resource ){
        /**检查站点*/
        siteAdviceService.existSite( site );
        /**检查设备编号*/
        Assert.hasText( resource, I18nUtil.getI18nText("common.resourceNotBlank") );

        return resourceAdviceMapper.selectCncType( site, resource );
    }

    /**
     * 检查设备是否一夹
     *
     * @param site
     * @param resource
     * @return
     */
    public boolean isCNC1( String site, String resource ){
        String resourceType = systemRuleAdviceService.existSystemRule( site, Constants.SYSTEM_RULE_RESOURCE_TYPE_CNC1 );

        Map<String,Object> resourceMap = resourceTypeAdviceService.findResourceByResourceType( site, resource, resourceType );
        if( resourceMap != null ){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 检查是否是cnc设备
     *
     * @param site
     * @param resource
     * @return
     */
    public boolean isCNC( String site, String resource ){

        String resourceBo = BOHandleUtil.buildResourceHandle( site, resource );
        String resourceType = customFieldsAdviceService.findCustomValue( resourceBo, Constants.RESRCE_CUSTOM_FIELD_RESOURCE_TYPE );
        if( "CNC".equals( resourceType ) ){
            return true;
        }
        return false;
    }

    /**
     * 查询夹位资源类型资源
     *
     * @param site
     * @param cncTye
     * @param resourceType
     * @return
     */
    public List<Map<String,Object>> findResourceListByCncType( String site, String cncTye, String resourceType ){
        /**检查站点*/
        siteAdviceService.existSite( site );
        /**检查资源类型*/
        Assert.hasText( resourceType, I18nUtil.getI18nText( "common.resourceTypeNotBlank" ) );

        if( StringUtils.isBlank( cncTye ) ){
            return resourceAdviceMapper.selectResourceListByType( site, resourceType );
        }

        return resourceAdviceMapper.selectResourceListByCncType( site, cncTye, resourceType );
    }

    /**
     * 查询资源所在工作中心列表
     *
     * @param site
     * @param resource
     * @return
     */
    public List<Map<String,Object>> findWorkCenterList( String site, String resource ){
        /**检查站点*/
        siteAdviceService.existSite( site );
        /**检查设备编号*/
        Assert.hasText( resource, I18nUtil.getI18nText("common.resourceNotBlank") );

        String resourceBo = BOHandleUtil.buildResourceHandle( site, resource );
        return resourceAdviceMapper.selectWorkCenterList( resourceBo );
    }

    /**
     * 查询资源所在工作中心
     *
     * @param site
     * @param resource
     * @return
     */
    public Map<String,Object> findWorkCenterMap( String site, String resource ){
        List<Map<String,Object>> workCenterList = findWorkCenterList( site, resource );
        if( workCenterList != null && workCenterList.size() > 0 ){
            return workCenterList.get( 0 );
        }else{
            return null;
        }
    }

    /**
     * 检查资源所在工作中心自定义字段是否是自动线
     *
     * @param site
     * @param resource
     * @return
     */
    public boolean isAutoLineResource( String site, String resource ){
        Map<String,Object> workCenterMap = findWorkCenterMap( site, resource );
        if( workCenterMap != null ) {
            String autoLine = customFieldsAdviceService.findCustomValue((String) workCenterMap.get("HANDLE"), Constants.WORK_CENTER_CUSTOM_FIELD_AUTOLINE);
            if ("Y".equalsIgnoreCase(autoLine)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 查询资源所在工作中心
     *
     * @param site
     * @param resource
     * @return
     */
    public String findWorkCenter( String site, String resource ){
        Map<String,Object> workCenterMap = findWorkCenterMap( site, resource );
        if( workCenterMap != null ){
            return (String) workCenterMap.get( "WORK_CENTER" );
        }else{
            return null;
        }
    }

    /**
     * 查询工作中心资源
     *
     * @param site
     * @param workCenter
     * @return
     */
    public List<String> findResourceListByWorkCenter( String site, String workCenter ){
        Assert.hasText( site, I18nUtil.getI18nText( "common.siteNotBlank" ) );
        Assert.hasText( workCenter, I18nUtil.getI18nText( "common.workCenterNotBlank" ) );

        String workCenterBo = BOHandleUtil.buildWorkCenterHandle( site, workCenter );
        return resourceAdviceMapper.selectResourceListByWorkCenter( workCenterBo );
    }

    /**
     * 查询自动线资源
     *
     * @param site
     * @return
     */
    public List<Map<String,Object>> findAutoLineResource( String site ){
        Assert.hasText( site, I18nUtil.getI18nText( "common.siteNotBlank" ) );
        return resourceAdviceMapper.findAutoLineResource( site );
    }

    
    /**
     * 查询站点所有资源
     *
     * @param site
     * @return
     */
    @Override
    public List<Map<String, Object>> findResrceBySite(String site) {
        List<Map<String, Object>> list = resourceAdviceMapper.selectResrceBySite(site);
        return list;
    }


    /**
     * 查询设备工作中心接驳站
     *
     * @param site
     * @param resource
     * @return
     */
    public String findTranship( String site, String resource ){
        Map<String,Object> workCenterMap = findWorkCenterMap( site, resource );
        if( workCenterMap == null ){
            throw BusinessException.build( "common.resourceWorkCenterNotExist", new String[]{ resource } );
        }
        String workCenterBo = (String) workCenterMap.get( "HANDLE" );
        String tranship = customFieldsAdviceService.existCustomValue( workCenterBo, Constants.WORK_CENTER_CUSTOM_FIELD_TRANSHIP );
        return tranship;
    }


    /**
     * 查询设备状态
     *
     * @param site
     * @param resource
     * @return
     */
    public String findResourceStatus( String site, String resource ){
        Assert.hasText( site, I18nUtil.getI18nText( "common.siteNotBlank" ) );
        Assert.hasText( resource, I18nUtil.getI18nText( "common.resourceNotBlank" ) );

        /*ResourceTimeLog resourceTimeLog = resourceTimeLogAdviceMapper.selectCurrentResourceTimeLog( site, resource );
        if( resourceTimeLog != null ){
            return resourceTimeLog.getStatus();
        }*/
        String resourceBo = BOHandleUtil.buildResourceHandle( site, resource );
        String status = customFieldsAdviceService.findCustomValue( resourceBo, Constants.RESRCE_CUSTOM_FIELD_STATUS );
        return status;
    }

    /**
     * 查询设备可切换状态列表
     *
     * @param site
     * @param resource
     * @param status
     * @return
     */
    public List<String> findNextStatus( String site, String resource, String status ){
        Assert.hasText( site, I18nUtil.getI18nText( "common.siteNotBlank" ) );
        Assert.hasText( resource, I18nUtil.getI18nText( "common.resourceNotBlank" ) );
        Assert.hasText( status, I18nUtil.getI18nText( "common.resourceStatusNotBlank" ));
        List<String> nextStatusList = resourceStatusMap.get( status );
        if( nextStatusList == null ){
            nextStatusList = new ArrayList<>();
        }
        return nextStatusList;
    }

    /**
     * 保存设备状态
     *
     * @param site
     * @param resource
     * @param status
     */
    public void updateResourceStatus( String site, String resource, String status ){
        Assert.hasText( site, I18nUtil.getI18nText( "common.siteNotBlank" ) );
        Assert.hasText( resource, I18nUtil.getI18nText( "common.resourceNotBlank" ) );

        String resourceBo = BOHandleUtil.buildResourceHandle( site, resource );
        customFieldsAdviceService.updateCustomField( resourceBo, Constants.RESRCE_CUSTOM_FIELD_STATUS, status );
    }

    /**
     * 修改设备状态
     *
     * @param site
     * @param resource
     * @param status
     */
    @Transactional( propagation = Propagation.REQUIRED,rollbackFor = Exception.class )
    public void changeResourceStatus( String site, String resource, String status ){
        /**检查设备*/
        existResource( site, resource );
        /**检查状态*/
        Assert.hasText( status, I18nUtil.getI18nText( "common.resourceStatusNotBlank" ));
        /**检查时间*/
        //Assert.notNull( changeDate, I18nUtil.getI18nText( "common.sendTimeNotNull" ) );
        Date changeDate = new Date();

        updateResourceStatus( site, resource, status );

        if( !resourceStatusMap.containsKey( status ) ){
            throw BusinessException.build( "common.resourceStatusNotSupport", new String[]{ status } );
        }

        ResourceTimeLog resourceTimeLog = resourceTimeLogAdviceMapper.selectCurrentResourceTimeLogForUpdate( site, resource );
        if( resourceTimeLog == null ){
            saveResourceTimeLog( site, resource, status, changeDate );
            return;
        }

        /**检查要切换设备状态是否*/
        List<String> nextStatusList = resourceStatusMap.get( resourceTimeLog.getStatus() );
        if( !resourceTimeLog.getStatus().equals( status ) && !nextStatusList.contains( status ) ){
            throw BusinessException.build( "common.resourceStatusNotValid", new String[]{ resourceTimeLog.getStatus(), status, nextStatusList.toString() } );
        }

        if( !resourceTimeLog.getStatus().equals( status ) ){
            resourceTimeLog.setEndDateTime( changeDate );
            resourceTimeLog.setElapsedTime( resourceTimeLog.getEndDateTime().getTime() - resourceTimeLog.getStartDateTime().getTime() );
            resourceTimeLogService.updateResourceTimeLog( resourceTimeLog );
            saveResourceTimeLog( site, resource, status, changeDate );
            return;
        }
    }

    public void saveResourceTimeLog( String site, String resource, String status, Date changeDate ){
        ResourceTimeLog resourceTimeLog = new ResourceTimeLog();
        resourceTimeLog.setHandle( BOHandleUtil.buildResourceTimeLogHandle() );
        resourceTimeLog.setSite( site );
        resourceTimeLog.setResrce( resource );
        resourceTimeLog.setStatus( status );
        resourceTimeLog.setStartDateTime( changeDate );
        resourceTimeLogService.insertResourceTimeLog( resourceTimeLog );
    }



    static{
        List<String> idleNextStatusList = new ArrayList<>();
        idleNextStatusList.add( "RUN" );
        idleNextStatusList.add( "STOP" );
        resourceStatusMap.put( "IDLE", idleNextStatusList );

        List<String> runNextStatusList = new ArrayList<>();
        runNextStatusList.add( "IDLE" );
        runNextStatusList.add( "STOP" );
        resourceStatusMap.put( "RUN", runNextStatusList );

        List<String> stopNextStatusList = new ArrayList<>();
        stopNextStatusList.add( "IDLE" );
        stopNextStatusList.add( "RUN" );
        stopNextStatusList.add( "DOWN" );
        stopNextStatusList.add( "TPM" );
        resourceStatusMap.put( "STOP", stopNextStatusList );

        List<String> downNextStatusList = new ArrayList<>();
        downNextStatusList.add( "REPAIR" );
        resourceStatusMap.put( "DOWN", downNextStatusList );

        List<String> tpmNextStatusList = new ArrayList<>();
        tpmNextStatusList.add( "IDLE" );
        resourceStatusMap.put( "TPM", tpmNextStatusList );

        List<String> repairNextStatusList = new ArrayList<>();
        repairNextStatusList.add( "IDLE" );
        resourceStatusMap.put( "REPAIR", repairNextStatusList );
    }
}
